﻿using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.IO;

namespace OpenLS.Spreadsheet.Formats.Biff.Records
{
    internal class FtLbsData
    {
        private readonly List<bool> _bsels = new List<bool>();
        private readonly List<XLUnicodeString> _rgLines = new List<XLUnicodeString>();
        private ushort _cLines;
        private ushort _cbFContinued;
        private LbsDropData _dropData;
        private bool _fNo3D;
        private bool _fUseCb;
        private bool _fValidIds;
        private bool _fValidPlex;
        private ObjFmla _fmla;
        private ushort _iSel;
        private ushort _idEdit;
        private byte _lct;
        private bool _reserved;
        private bool _unused;
        private byte _wListSelType;

        public void Read(BinaryReader reader, FtCmoObjectType ot)
        {
            ushort ft = reader.ReadUInt16();
            Contract.Assert(ft == 0x0013);
            _cbFContinued = reader.ReadUInt16();
            _fmla = new ObjFmla();
            _fmla.Read(reader, false);
            _cLines = reader.ReadUInt16();
            _iSel = reader.ReadUInt16();
            byte abcdefg = reader.ReadByte();
            _fUseCb = (abcdefg & 0x01) != 0;
            _fValidPlex = (abcdefg & 0x02) != 0;
            _fValidIds = (abcdefg & 0x04) != 0;
            _fNo3D = (abcdefg & 0x08) != 0;
            _wListSelType = (byte)((abcdefg >> 4) & 0x003); //\\ sure?
            _unused = (abcdefg & 0x040) != 0;
            _reserved = (abcdefg & 0x080) != 0;
            _lct = reader.ReadByte();
            _idEdit = reader.ReadUInt16();
            if (ot == (FtCmoObjectType)0x0014)
            {
                _dropData = new LbsDropData();
                _dropData.Read(reader);
            }
            _rgLines.Clear();
            if (_fValidPlex)
            {
                for (int i = 0; i < _cLines; i++)
                {
                    var s = new XLUnicodeString();
                    s.Read(reader);
                    _rgLines.Add(s);
                }
            }
            if (_wListSelType != 0)
            {
                _bsels.Clear();
                for (int i = 0; i < _cLines; i++)
                {
                    _bsels.Add(reader.ReadByte() != 0);
                }
            }
        }

        public void Write(BinaryWriter writer)
        {
            const ushort ft = 0x0013;
            writer.Write(ft);
            writer.Write(_cbFContinued);
            _fmla.Write(writer);
            writer.Write(_cLines);
            writer.Write(_iSel);
            byte abcdefg = 0;
            if (_fUseCb) abcdefg |= 0x01;
            if (_fValidPlex) abcdefg |= 0x02;
            if (_fValidIds) abcdefg |= 0x04;
            if (_fNo3D) abcdefg |= 0x08;
            abcdefg |= (byte)(_wListSelType << 4);
            if (_unused) abcdefg |= 0x040;
            if (_reserved) abcdefg |= 0x080;
            writer.Write(abcdefg);
            writer.Write(_lct);
            writer.Write(_idEdit);
            if (_dropData != null)
                _dropData.Write(writer);
            if (_fValidPlex)
            {
                foreach (XLUnicodeString item in _rgLines)
                    item.Write(writer);
            }
            if (_wListSelType != 0)
            {
                foreach (bool item in _bsels)
                {
                    writer.Write((item ? (byte)1 : (byte)0));
                }
            }
        }
    }
}